home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / hardware / int24-c2 / int24.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-04-16  |  5.1 KB  |  199 lines

  1. /********************************************************
  2.  int24.c
  3.  
  4.  (C) 1990 Joel Spolsky, All Rights Reserved.
  5.  
  6.  This code is released into the public domain by the author.
  7.  You can do whatever you want with it. Please let me know
  8.  if you find it useful or if you find any bugs.
  9.  *********************************************************/
  10.  
  11. /** int24.c
  12.  **
  13.  ** Interrupt 24 Handler version 0.9
  14.  **
  15.  ** When DOS has trouble accessing a peripheral it
  16.  ** calls Interrupt 0x24. This is usually a pointer to
  17.  ** the code in COMMAND.COM that prints the "Abort, Retry,
  18.  ** Ignore" message. This is a completely portable module
  19.  ** that replaces that message with a slightly more aesthetic
  20.  ** one.
  21.  **
  22.  ** To use it, just call install_24(). To restore the DOS
  23.  ** handler, call uninstall_24(). Warning! If you ever go
  24.  ** into graphics mode of some sort, uninstall this! It won't
  25.  ** be able to deal with a graphics screen correctly.
  26.  **
  27.  ** Note: We don't let the user ignore the error, which they shouldn't
  28.  ** be doing anyway.
  29.  **
  30.  ** HISTORY
  31.  ** -------
  32.  ** 19 Mar 90    Created JS
  33.  ** 16 Apr 90   Fixed to eliminate call to bioskey, which was reentering DOS
  34.  **/
  35.  
  36. #include <bios.h>
  37. #include <dos.h>
  38. #include <stdio.h>
  39.  
  40. #define CRIT_ERROR_HANDLER (0x24)
  41.  
  42. /** FUNCTION PROTOTYPES **/
  43. void install_24(void);
  44. void uninstall_24(void);
  45. void interrupt handle_24 (unsigned bp, unsigned di, unsigned si,
  46.               unsigned ds, unsigned es, unsigned dx,
  47.               unsigned cx, unsigned bx, unsigned ax);
  48. void fastprintz(int x, int y, int attr, char *s);
  49. int getbioskey(void);
  50.  
  51. void interrupt (*oldvect)();              
  52. unsigned scr;                /* The segment where the screen is */
  53.  
  54. /** install_24
  55.  **
  56.  ** Installs the fancy interrupt handler.
  57.  **/
  58.  
  59. void install_24(void)
  60. {
  61.     oldvect = getvect(CRIT_ERROR_HANDLER);    /* save old handler */
  62.     setvect(CRIT_ERROR_HANDLER, handle_24); /* and install ours */
  63.  
  64.     /* Find out if the screen is at 0xB000 or 0xB800 */
  65.     _AH = 0x0F;
  66.     geninterrupt (0x10);
  67.     if (_AL == 7)
  68.         scr = 0xB000;
  69.     else
  70.         scr = 0xB800;
  71. }
  72.  
  73.  
  74. void uninstall_24(void)
  75. {
  76.     /* Restore old handler */
  77.     setvect(CRIT_ERROR_HANDLER, oldvect);
  78. }
  79.  
  80. static char screen_buf[9][52];    /* room for the saved part of screen */
  81.  
  82. void interrupt handle_24 (unsigned bp, unsigned di, unsigned si,
  83.               unsigned ds, unsigned es, unsigned dx,
  84.               unsigned cx, unsigned bx, unsigned ax)
  85. {
  86.  
  87.     int err,key,ret=-1;
  88.     int r,c,start;
  89.     
  90.     err = di & 0x00FF;    /* Error message, from DOS. */
  91.  
  92.     /* Save section of screen that will be overwritten */
  93.     for (r=8; r<17; r++) {
  94.         start = (160 * r + 54);
  95.         for (c=0; c<26; c++) {
  96.             screen_buf[r-8][c*2] = peekb(scr, start++);
  97.             screen_buf[r-8][c*2+1] = peekb(scr, start++);
  98.         } 
  99.     }
  100.  
  101.     /* Pop up error message */
  102.     fastprintz( 8,27,0x07,"╓────────────────────────╖");
  103.     fastprintz( 9,27,0x07,"║Error!                  ║");
  104.     fastprintz(10,27,0x07,"║                        ║");
  105.  
  106.     /* Common diagnosable problems */
  107.     switch(err) {
  108.         case 0x00:
  109.     fastprintz(11,27,0x07,"║Disk is write protected.║"); break;
  110.         case 0x02:
  111.     fastprintz(11,27,0x07,"║Disk drive is not ready.║"); break;
  112.         default:
  113.     fastprintz(11,17,0x07,"║Disk error.             ║"); break;
  114.     }
  115.  
  116.     fastprintz(12,27,0x07,"║                        ║");
  117.     fastprintz(13,27,0x07,"║ Try again              ║");
  118.     fastprintz(13,29,0x0f,"T");
  119.     fastprintz(14,27,0x07,"║ Exit this program      ║");
  120.     fastprintz(14,29,0x0f,"E");
  121.  
  122.     /* In DOS 3.00 and later, they can also fail the disk access */
  123.     if (_osmajor > 2) {
  124.     fastprintz(15,27,0x07,"║ Cancel this operation  ║");
  125.     fastprintz(15,29,0x0f,"C");
  126.     }
  127.     else
  128.     fastprintz(15,27,0x07,"║                        ║");
  129.  
  130.     fastprintz(16,27,0x07,"╙────────────────────────╜");
  131.  
  132.     /* Call BIOS to get a single keystroke from the user */
  133.     do {
  134.         key=getbioskey();
  135.  
  136.         if (key & 0x00FF)
  137.             key &= 0x00FF;
  138.  
  139.         switch(key) {
  140.         case 't': case 'T': ret = 0x0001; break;
  141.         case 'e': case 'E': ret = 0x0002; break;
  142.         case 'c': case 'C': if (_osmajor > 2) ret = 0x0003; break;
  143.         default: break;
  144.         }
  145.  
  146.     } while (ret < 0);
  147.     
  148.     /* Restore that section of the screen */
  149.     for (r=8; r<17; r++) {
  150.         start = (160*r + 54);
  151.         for (c=0; c<26; c++) {
  152.             pokeb(scr, start++, screen_buf[r-8][c*2]);
  153.             pokeb(scr, start++, screen_buf[r-8][c*2+1]);
  154.         }
  155.     }
  156.  
  157.     ax = ret;
  158. /* And please don't tell me I didn't use any of those parameters. */
  159. #pragma warn -par
  160. }
  161. #pragma warn .par
  162.  
  163.  
  164. /* fastprintz - shove an asciz string onto the screen */
  165. void
  166. fastprintz(int y, int x, int attr, char *s)
  167. {
  168.     int i=0,base;
  169.  
  170.     base = (80*y+x)<<1;  /* determine offset into screen */
  171.     while (s[i]!=0) {
  172.         pokeb(scr, base++, s[i++]);
  173.         pokeb(scr, base++, attr);
  174.     }
  175. }
  176.  
  177. /** getbioskey
  178.  **
  179.  ** get one key from the BIOS
  180.  **
  181.  ** Like TC bioskey(0), but doesn't nab control Break. It seems
  182.  ** that the TC bioskey was trying to block Ctrl-Breaks, which
  183.  ** it did by changing the Ctrl-Break handler, which it called
  184.  ** DOS to do. This made the interrupt handler reenter DOS which
  185.  ** is illegal.
  186.  **/
  187.  
  188. int getbioskey(void)
  189. {
  190.     union REGS regs;
  191.     struct SREGS segregs;
  192.  
  193.     segread(&segregs);
  194.     regs.h.ah = 0;
  195.     int86x (0x16, ®s, ®s, &segregs);
  196.     return regs.x.ax;
  197. }
  198.  
  199.